package mdp.solve;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.concurrent.ArrayBlockingQueue;

import util.Pair;
import mdp.id.AADDHandler;
import mdp.id.ADDHandler;
import mdp.id.LogicRDDL2DD;
import mdp.id.LogicRDDL2DD.DEBUG;
import mdp.id.LogicRDDL2DD.ORDER;

public class PolicyIterationConcurrentAADD<T extends LogicRDDL2DD> implements Runnable {

	private T _handler;
	private ArrayBlockingQueue<Pair<T, Integer>> _bq = null;
	private int evalLength = 0;
	/**
	 * 
	 */
	public PolicyIterationConcurrentAADD(T handler, String domain, String instance, 
			ArrayBlockingQueue<Pair<T, Integer>> bq, int evallen) {
		_bq = bq;
		_handler = handler;
		_handler.buildFromFile(domain, instance);
		evalLength = evallen;
	}
	
	public void run() {
		
		int iter = 0;
		int pi = _handler.getInitialPolicy();
		int pid = -1;
		boolean done = false;
		long timetosolve = System.currentTimeMillis();
		while( !done ){
			Pair<Integer, Integer> vq = new Pair<Integer, Integer>(_handler.DD_ZERO, _handler.DD_ZERO);
			_handler.saveThis(pi);
			for( int i = 0 ; i < evalLength; ++i ){
				int v = _handler.swapForPrimes(vq._o1);
				vq = _handler.regress(v, pi, true, true);
				System.out.println("Eval iter  " + i );
//				_handler.flushCaches(false, vq._o1);
			}
			int v = _handler.swapForPrimes(vq._o1);
			vq = _handler.regress(v, null, true, true);
			pid = _handler.argMaxToNegInf(vq._o1, vq._o2);
			
			++iter;
			System.out.println("iteration " + iter);
			
			if( pi == pid ){//|| _handler.isHorizon(iter) ){
				done = true;
			}
			
			_handler.forgetThis(pi);
			pi = pid;
			
			_handler.flushCaches(false, pi);
//			_handler.showGraph(_handler._context.applyInt(pi, pid, DD.ARITH_MINUS));
		}
		pi = _handler.makePolicy(pi, _handler.DD_ZERO);
		timetosolve = System.currentTimeMillis()-timetosolve;
//		_handler.showGraph(pid);
//		_handler.showGraph(pi);
		_handler.setPolicyDD(pi);
		ArrayList stats = _handler.playDD(pi);
		stats.add(timetosolve/(1000*60d));
		System.out.println(stats);
		
		if( _bq != null ){
			try {
				_bq.put(new Pair<T, Integer>(_handler, pi));
			} catch (InterruptedException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		
	}

	public static void main(String[] args) throws InterruptedException {
		AADDHandler handle = new AADDHandler(DEBUG.PROBLEM_INFO , ORDER.INTERLEAVE);
		Runnable pic = 
			new PolicyIterationConcurrentAADD<AADDHandler>(handle, args[0], args[1], null, Integer.parseInt(args[2]));
		
		Thread picWorker = new Thread(pic, "PIC");
		picWorker.start();
		picWorker.join();
	}
}
